package com.wangzhenyu.learn.test.kotlin.weituo

import kotlin.properties.Delegates
import kotlin.properties.ReadOnlyProperty
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

@Suppress("UNUSED")
object InstanceDelegate {

    //委托属性的使用
    //延迟属性:指的是属性只在第一次访问的时候才会计算，之后则会将之前的计算结果缓存起来供后续调用
    fun test01() {
        val temp = DelegateTest01()
        println(temp.a)
    }

    //可观测属性
    fun test02() {
        val temp = DelegateTest02()
        temp.a = 50
        println(temp.a)

        println("===========")
        println(temp.b)
        temp.b = 30
        println(temp.b)
        temp.b = 15
        println(temp.b)
    }

    //非空属性：适用于那些无法在初始化阶段就确定属性值的场合
    fun test03() {
        val temp = DelegateTest03()
        temp.a = "Hello"
        println(temp.a)
    }

    //map属性
    fun test04() {
        val map = mapOf("name" to "WZY", "age" to 25, "address" to "ShangHai")
        val temp = DelegateTest04(map)
        println(temp.name)
        println(temp.age)
        println(temp.address)
        println("====================")

        //map来托管委托的值
        val map2: MutableMap<String, Any?> =
            mutableMapOf("name" to "WZY", "age" to 25, "address" to "ShangHai")
        val temp2 = DelegateTest05(map2)
        println(temp2.name)
        println(temp2.age)
        println(temp2.address)
        temp2.age = 26
        println(temp2.age)
        println(map2)
    }

    fun test05() {
        val temp = DelegateTest06()
        println(temp.age)
    }
}

class DelegateTest01 {
    val a: String by lazy {
        println("Hello")
        "Hi"
    }
}

class DelegateTest02 {

    var a: Int by Delegates.observable(20)
    { property, oldValue, newValue ->
        println("${property.name}的旧值是${oldValue}新值是${newValue}")
    }

    //在属性赋值前进行判断
    //这个20是初始值
    var b: Int by Delegates.vetoable(20)
    { _, oldValue, newValue ->
        when {
            oldValue >= newValue -> false
            else -> true
        }
    }
}

class DelegateTest03 {
    //赋上初值才能使用
    var a: String by Delegates.notNull()
}

class DelegateTest04(map: Map<String, Any?>) {

    val name: String by map

    val age: Int by map

    val address: String by map
}

class DelegateTest05(map: MutableMap<String, Any?>) {

    var name: String by map

    var age: Int by map

    var address: String by map
}

@Suppress("UNUSED")
class TestDelegateExample {
    // 被委托属性
    var prop: String by TestDelegate()
}

// 基础类
class TestDelegate {

    //thisRef表示被委托的属性所在的对象
    //property表示被委托的属性本身
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef,your delegated property nam is ${property.name}"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$thisRef,new value is $value")
    }

}

//提供委托（providing a delegate）
//通过定义provideDelegates operator，我们可以扩展委托的创建逻辑过程。如果对象定义了provideDelegate方法，那么该方法就会被调用来创建属性委托实例

class DelegateTest07 : ReadOnlyProperty<DelegateTest06, String> {
    override fun getValue(thisRef: DelegateTest06, property: KProperty<*>): String {
        return "hello"
    }
}

class TestLaunch01 {

    operator fun provideDelegate(
        thisRef: DelegateTest06,
        property: KProperty<*>
    ): ReadOnlyProperty<DelegateTest06, String> {
        when (property.name) {
            "name", "age" -> return DelegateTest07()
            else -> throw Exception("错误")
        }
    }
}

class DelegateTest06 {
    val name: String by TestLaunch01()
    val age: String by TestLaunch01()
}